home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Atari Compendium
/
The Atari Compendium (Toad Computers) (1994).iso
/
files
/
umich
/
music
/
eked-m1.zoo
/
src
/
gm
/
wind_man.c
< prev
Wrap
C/C++ Source or Header
|
1995-02-19
|
26KB
|
881 lines
/*
* EKED-M1 : Editor for Korg M1 synth; wind_man.c : window manager
* Copyright (C) 1995 Steven M. Eker (Steven.Eker@brunel.ac.uk)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stddef.h>
#include <osbind.h> /* for Vsync() */
#include <gemfast.h>
#include <aesbind.h>
#include <vdibind.h>
#include "gem_man.h"
#define WM_HASH(h) (((unsigned) (h)) % MAX_WINDOWS)
#define LSB_COPY(d, s) ((d) ^ (((s) ^ (d)) & 1))
#define LSB_NEQ(n, m) (((n) ^ (m)) & 1)
#define MAKE_EVEN(n) ((n) & ~1)
typedef struct window_struct {
int aes_handle; /* aes handle for window */
int parts; /* window part flags */
int con_w; /* width of contents */
int con_h; /* height of contents */
int x_offset; /* x offset of visible portion of contents */
int y_offset; /* y offset of visible portion of contents */
int x_scroll; /* number of pixels for hscroll step */
int y_scroll; /* number of pixels for vscroll step */
DISP_FUNC_PTR display; /* pointer to display code for contents */
ACT_FUNC_PTR action; /* pointer to action code for window */
long usr_val; /* user value */
struct window_struct *above; /* pointer to window above us */
struct window_struct *below; /* pointer to window below us */
} WINDOW;
static WINDOW wm_table[MAX_WINDOWS];
static WINDOW *top_win;
static WINDOW *bot_win;
static GRECT used_stack[MAX_WINDOWS];
static int used_top = -1;
static int roll_handle;
static int quiting = FALSE;
static WINDOW *get_window(int h);
static void wm_resized(int handle, GRECT *area);
static void wm_hscroll(int handle, int offset, WINDOW *w, GRECT *area);
static void wm_vscroll(int handle, int offset, WINDOW *w, GRECT *area);
static void roll_redraw(OBJECT *tree, int ob, GRECT *area);
#define PUSH(w) \
( \
(w)->above = NULL, \
(w)->below = top_win, \
top_win ? (top_win->above = (w)) : (bot_win = (w)), \
top_win = (w) \
)
#define YANK(w) \
( \
((w)->above ? ((w)->above->below = (w)->below) : \
(top_win = (w)->below)), \
((w)->below ? ((w)->below->above = (w)->above) : \
(bot_win = (w)->above)) \
)
/*
* Basic window management functions
*/
static WINDOW *get_window(int h)
{
WINDOW *start = wm_table + WM_HASH(h), *w = start;
while(w->aes_handle != h){
if(++w == wm_table + MAX_WINDOWS)
w = wm_table;
if(w == start)
/*
* wind_find() gave us someone elses window
* or window has closed since message was generated.
*/
return NULL;
}
return w;
}
void wm_getdata(int handle, int *x_pos, int *y_pos, long *usr_val)
{
WINDOW *w = get_window(handle);
GRECT rect;
wind_get(handle, WF_WORKXYWH, &rect.g_x, &rect.g_y, &rect.g_w, &rect.g_h);
*x_pos = rect.g_x - w->x_offset;
*y_pos = rect.g_y - w->y_offset;
*usr_val = w->usr_val;
}
void wm_send_redraw(int handle, GRECT *area)
{
static int msg[] = {WM_REDRAW, 0, 0, 0, 0, 0, 0, 0};
msg[1] = gl_apid;
msg[3] = handle;
if(area == NULL)
wind_get(handle, WF_WORKXYWH, msg + 4, msg + 5, msg + 6, msg + 7);
else
*((GRECT *) (msg + 4)) = *area;
appl_write(gl_apid, (int) sizeof(msg), msg);
}
void wm_send_user(int handle, long object)
{
WINDOW *w = get_window(handle);
GRECT rect;
wind_get(handle, WF_WORKXYWH, &rect.g_x, &rect.g_y, &rect.g_w, &rect.g_h);
(*(w->action))(w->aes_handle, E_USER, (void *) object,
rect.g_x - w->x_offset, rect.g_y - w->y_offset, w->usr_val);
}
void wm_exit()
{
WINDOW *w;
quiting = TRUE;
for(w = wm_table; w < wm_table + MAX_WINDOWS; w++){
if(w->aes_handle != 0)
wm_closed(w->aes_handle);
}
}
int wm_open(int parts, GRECT *init, char *title,
int con_w, int con_h, int x_scroll, int y_scroll,
DISP_FUNC_PTR display, ACT_FUNC_PTR action, long usr_val)
{
WINDOW *start, *w;
GRECT max, work;
int h;
wind_calc(WC_BORDER, parts, 0, 0, con_w, con_h,
&max.g_x, &max.g_y, &max.g_w, &max.g_h);
if(max.g_w > desk.g_w)
max.g_w = desk.g_w - LSB_NEQ(max.g_w, desk.g_w);
if(max.g_h > desk.g_h)
max.g_h = desk.g_h - LSB_NEQ(max.g_h, desk.g_h);
max.g_x = desk.g_x;
max.g_y = desk.g_y;
h = wind_create(parts, max.g_x, max.g_y, max.g_w, max.g_h);
if(h < 0)
return OUT_OF_WINDOWS;
start = wm_table + WM_HASH(h);
for(w = start; w->aes_handle != 0;){
if(++w == wm_table + MAX_WINDOWS)
w = wm_table;
if(w == start){
wind_delete(h);
return OUT_OF_WINDOWS;
}
}
if(init != NULL){
init->g_x = MAKE_EVEN(init->g_x);
init->g_y = MAKE_EVEN(init->g_y);
if(init->g_w > max.g_w)
init->g_w = max.g_w;
else
init->g_w += LSB_NEQ(con_w, init->g_w);
if(init->g_h > max.g_h)
init->g_h = max.g_h;
else
init->g_h += LSB_NEQ(con_h, init->g_h);
}
else if(used_top >= 0){
init = &(used_stack[used_top--]);
if(init->g_w > max.g_w || !(parts & HSLIDE))
init->g_w = max.g_w;
if(init->g_h > max.g_h || !(parts & VSLIDE))
init->g_h = max.g_h;
}
else
init = &max;
w->aes_handle = h;
w->parts = parts;
w->con_w = con_w;
w->con_h = con_h;
w->x_scroll = x_scroll;
w->y_scroll = y_scroll;
w->x_offset = 0;
w->y_offset = 0;
w->usr_val = usr_val;
w->display = display;
w->action = action;
PUSH(w);
wind_set(h, WF_NAME, title, 0, 0);
if(parts & (HSLIDE | VSLIDE)){
wind_calc(WC_WORK, parts, init->g_x, init->g_y, init->g_w, init->g_h,
&work.g_x, &work.g_y, &work.g_w, &work.g_h);
if(parts & HSLIDE){
wind_set(h, WF_HSLSIZE, (int) RDIV(1000L * work.g_w, con_w), 0, 0, 0);
wind_set(h, WF_HSLIDE, 0, 0, 0, 0);
}
if(parts & VSLIDE){
wind_set(h, WF_VSLSIZE, (int) RDIV(1000L * work.g_h, con_h), 0, 0, 0);
wind_set(h, WF_VSLIDE, 0, 0, 0, 0);
}
}
wind_open(h, init->g_x, init->g_y, init->g_w, init->g_h);
return h;
}
void wm_closed(int h)
{
WINDOW *w = get_window(h);
(void) (*(w->action))(w->aes_handle, E_CLEANUP, (void *) NULL,
0, 0, w->usr_val);
if(used_top < MAX_WINDOWS - 1){
used_top++;
wind_get(h, WF_CURRXYWH,
&(used_stack[used_top].g_x), &(used_stack[used_top].g_y),
&(used_stack[used_top].g_w), &(used_stack[used_top].g_h));
}
wind_close(h);
wind_delete(h);
YANK(w);
w->aes_handle = 0;
/*
* Avoid build up of stale messages from successive closes.
*/
wm_flush(!quiting);
}
void wm_redraw(int handle, GRECT *area)
{
WINDOW *w = get_window(handle);
DISP_FUNC_PTR display = w->display;
GRECT rect;
int x_pos, y_pos;
if(w == NULL)
return; /* processing stale redraw message */
wind_get(handle, WF_WORKXYWH, &rect.g_x, &rect.g_y, &rect.g_w, &rect.g_h);
x_pos = rect.g_x - w->x_offset;
y_pos = rect.g_y - w->y_offset;
wind_update(BEG_UPDATE);
graf_mouse(M_OFF, 0L);
wind_get(handle, WF_FIRSTXYWH, &rect.g_x, &rect.g_y, &rect.g_w, &rect.g_h);
while(rect.g_w != 0 && rect.g_h != 0){
if(intersect(area, &rect))
(*display)(x_pos, y_pos, &rect, w->usr_val);
wind_get(handle, WF_NEXTXYWH, &rect.g_x, &rect.g_y, &rect.g_w, &rect.g_h);
}
graf_mouse(M_ON, 0L);
wind_update(END_UPDATE);
}
void wm_moved(int handle, GRECT *area)
{
wind_set(handle, WF_CURRXYWH, LSB_COPY(are